package juc;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Description:
 *      两个线程交替输出
 *                 第一个线程：1 2 3 4 5 6 7
 *                 第二个线程： A B C D E F G
 *                 第三个线程：  ~!@#$%^
 *        输出结果：1A!2B@3C#4D$5E%6F^7G&
 */
public class Test07 {

    public static void main(String[] args){
        char[] nums = "1234567".toCharArray();
        char[] chars = "ABCDEFG".toCharArray();
        char[] signs = "~!@#$%^".toCharArray();

        /**
         * 每一个Condition都有一个队列，cT1的条件队列里有线程t1，cT2的条件队列里有线程t2。每个队列里的线程都是通过await释放锁，通过signal唤醒。
         *
         * 可以使用多个Condition精确的控制程序的打印.
         *
         * 也需要使用CountDownLantch精确的让哪一个线程先执行
         *
         */
        ReentrantLock lock = new ReentrantLock();
        Condition cT1 = lock.newCondition();
        Condition cT2 = lock.newCondition();
        Condition cT3 = lock.newCondition();

        Thread t1 = new Thread(()->{

            lock.lock();

            try{
                for (char temp : nums){
                    System.out.println(temp);
                    // 通知第二个线程执行，让第一个线程等待
                    cT2.signal();
                    cT1.await();
                }
                cT2.signal();
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        });

        Thread t2 = new Thread(()->{

            lock.lock();

            try{
                for (char temp : chars){
                    System.out.println(temp);
                    // 通知第三个线程执行，让第二个线程等待
                    cT3.signal();
                    cT2.await();
                }
                cT3.signal();
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        });

        Thread t3 = new Thread(()->{

            lock.lock();

            try{
                for (char temp : signs){
                    System.out.println(temp);
                    // 通知第一个线程执行，让第三个线程等待
                    cT1.signal();
                    cT3.await();
                }
                cT1.signal();
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        });

        t1.start();
        t2.start();
        t3.start();
    }
}
